open Graph

let (|>) x y = y x

(* We use Unit type for edges to solve a problem with unmatched signatures *)
(* in Dot.Parse second argument's edge function *)

module Unit = struct
	type t = unit
	let compare _ _ = 0 
	let default = ()
end 
(* we'll use true in snd argument to mark cover's member *)
module StrBool = struct
  type t = string * bool
end
module G = Persistent.Graph.AbstractLabeled(StrBool)(Unit)

(* Dot format input/output *)
module B = Builder.P(G)
module DotInput = 
  Dot.Parse
    (B)
    (struct 
      let node (id,_) _ = match id with
	| Dot_ast.Ident s
	| Dot_ast.Number s
	| Dot_ast.String s
	| Dot_ast.Html s -> (s,false)
      let edge _ = ()
    end)

module Display = struct
  include G
  let vertex_name v = String.escaped (V.label v |> fst)
  let graph_attributes _ = []
  let default_vertex_attributes _ = []
  let vertex_attributes v = 
		if G.V.label v |> snd 
		then [`Label "cover's member"; `Shape `Box] else [`Label ""; `Shape `Circle]
  let default_edge_attributes _ = []
  let edge_attributes _ = []
  let get_subgraph _ = None
end
module DotOutput = Graphviz.Neato(Display)

open Cover
module C = Cover(G)

open Timer
module T = Timer

let () =  
	try 
		let input = DotInput.parse Sys.argv.(1) in
		Printf.printf "Determine number of populations. For most graphs 5 is enouph.\n";
		let numberOfPop = read_line () |> int_of_string
		in
		let (cover,usefull), time = 
			let now = T.now() in
			T.calc_exec_time (C.geneticAlgorithm input numberOfPop) now in
		
		print_string "Generic algorithm\n";
		Printf.printf "Exec time: %f seconds\n" time;
		Printf.printf "Size of founded cover: %i\n" (List.length cover);
		Printf.printf "Usefull populations: %i\n" (usefull);
		try
			let oc = open_out Sys.argv.(2) in
			(*create a new vertices, (_,true) - cover members*)
      let newVertices = G.fold_vertex 
                             (fun v vs -> 
                                 if (List.mem v cover)
                                 then (G.V.create (fst (G.V.label v),true))::vs
                                 else v::vs) input []
      in
      (*new Graph without edges*)
      let vertexGraph = (List.fold_left (fun g v -> G.add_vertex g v) G.empty newVertices) in
		  (*find vertex by name*)
		  let findVertex v = List.find (fun w -> (fst (G.V.label w)) == (fst (G.V.label v))) in          
		  G.fold_edges (fun v1 v2 g -> 
			    G.add_edge g (findVertex v1 newVertices) (findVertex v2 newVertices)) input vertexGraph
			|> DotOutput.output_graph oc;
		  close_out oc; 
		with Invalid_argument _ -> 
			print_string "If you want to get graph with cover, you need to determine
			second argument - output-dot file.";
	with 
		| Invalid_argument _ -> print_string "Please, specify the input file."
		| Sys_error s -> print_string s; 
		| Failure s -> print_string ("Incorrect file format. " ^ s);

